package com.kun.video.ui.control.button;

import cn.hutool.core.util.StrUtil;
import com.kun.video.context.ContextService;
import com.kun.video.exception.Assert;
import com.kun.video.thread.ComThreadPool;
import com.kun.video.ui.ComponentUtil;
import com.kun.video.ui.KunComponent;
import com.kun.video.util.ComUtil;
import javafx.animation.*;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.css.PseudoClass;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Pos;
import javafx.scene.CacheHint;
import javafx.scene.Node;
import javafx.scene.Parent;
import javafx.scene.control.Button;
import javafx.scene.control.ContentDisplay;
import javafx.scene.control.Label;
import javafx.scene.control.Tooltip;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.HBox;
import javafx.scene.layout.StackPane;
import javafx.scene.paint.Color;
import javafx.scene.paint.Paint;
import javafx.scene.shape.Circle;
import javafx.scene.shape.SVGPath;
import javafx.scene.transform.Rotate;
import javafx.util.Duration;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.concurrent.CompletableFuture;

/**
 * TODO
 *
 * @author gzc
 * @since 2025/3/18 2:04
 **/
public abstract class AbstractButton extends Button implements KunComponent {
    private static final Logger log = LoggerFactory.getLogger(AbstractButton.class);

    private static final String STYLE_CLASS = "kun-button";
    /**
     * 默认透明度
     */
    private static final double DEFAULT_OPACITY = 0.9;
    /**
     * 动画持续时间
     */
    private static final Duration DEFAULT_ANIM_DURATION = Duration.millis(0);
    /**
     * CSS伪类定义
     */
    private static final PseudoClass HOVER_PSEUDO_CLASS = PseudoClass.getPseudoClass("hover");
    private static final PseudoClass PRESSED_PSEUDO_CLASS = PseudoClass.getPseudoClass("pressed");
    /**
     * 享元模式共享动画资源
     */
    private static volatile FadeTransition sharedFadeIn;
    private static volatile FadeTransition sharedFadeOut;
    /**
     * 状态标志位（使用位运算优化内存占用）
     */
    private byte stateFlags = 0b00000000;
    private static final byte HOVER_FLAG = 0b00000001;
    private static final byte PRESSED_FLAG = 0b00000010;
    /**
     * 点击按钮后，执行事件时的加载中动画
     */
    private Circle progressIndicator;
    private RotateTransition loadingAnimation;
    /**
     * 按钮图标
     */
    private final ObjectProperty<Object> svgGraphicProperty = new SimpleObjectProperty<>(this, "svgGraphic");
    /**
     * 按钮文本
     */
    protected Label textLabel;
    /**
     * 操作状态
     */
    protected boolean isProcessing = false;
    /**
     * 按钮事件
     */
    protected ButtonEvent buttonEvent;
    /**
     * 上一次触发的事件ID
     */
    protected String lastEventId;

    protected ComThreadPool comThreadPool;

    static {
        synchronized (AbstractButton.class) {
            // 初始化共享动画资源（线程安全）
            if (sharedFadeIn == null) {
                sharedFadeIn = createFadeTransition(1.0);
                sharedFadeOut = createFadeTransition(DEFAULT_OPACITY);
            }
        }
    }

    protected AbstractButton(Node svgGraphic, String tipText) {
        this(null, svgGraphic, tipText);
    }

    protected AbstractButton(String buttonText) {
        this(buttonText, null, buttonText);
    }

    protected AbstractButton(String buttonText, String tipText) {
        this(buttonText, null, tipText);
    }

    /**
     * 构造抽象按钮
     *
     * @param buttonText 按钮显示文本
     * @param svgGraphic 按钮图形（SVG节点）
     * @param tipText    悬浮提示文本
     */
    protected AbstractButton(String buttonText, Node svgGraphic, String tipText) {
        if (StrUtil.isNotBlank(buttonText)) {
            setText(buttonText);
        }
        if (StrUtil.isNotBlank(tipText)) {
            setTooltip(new Tooltip(tipText));
        }
        KunComponent.super.initialize();
        setGraphic(createGraphicBox(textLabel, svgGraphic));
    }

    @Override
    public void initStyleClass() {
        KunComponent.super.initStyleClass();
    }

    @Override
    public Parent getNode() {
        return this;
    }

    @Override
    public String getStyleName() {
        return STYLE_CLASS;
    }

    @Override
    public void initStyle() {

    }

    @Override
    public void initLayout() {
        // 启用缓存加速渲染
        setCache(true);
        // 优化渲染性能
        setCacheHint(CacheHint.SPEED);
        // 精确点击区域检测
        setPickOnBounds(true);
        // 避免亚像素渲染
        setSnapToPixel(true);
        setOpacity(DEFAULT_OPACITY);
        // 创建独立文本标签（与按钮文本绑定）
        textLabel = new Label();
//        textLabel.setTextFill(Paint.valueOf("#2c74fd"));
        textLabel.textProperty().bind(textProperty());
    }

    @Override
    public void initAnimation() {
        // 加载动画指示器
        progressIndicator = new Circle(8);
        progressIndicator.setVisible(false);
        progressIndicator.setMouseTransparent(true);
        progressIndicator.setStroke(Color.BLUE);
        // 虚线边框
        progressIndicator.getStrokeDashArray().addAll(5.0, 5.0);
        progressIndicator.setFill(Color.TRANSPARENT);
        progressIndicator.setStrokeWidth(2);
        // 设置几何中心（如果布局有偏移）
        progressIndicator.setCenterX(progressIndicator.getRadius());
        progressIndicator.setCenterY(progressIndicator.getRadius());
        // 层级提升
        progressIndicator.setTranslateZ(1);

        // 旋转动画配置
        loadingAnimation = new RotateTransition(Duration.seconds(1), progressIndicator);
        loadingAnimation.setByAngle(360);
        loadingAnimation.setCycleCount(Animation.INDEFINITE);
        loadingAnimation.setInterpolator(Interpolator.LINEAR);
        // 明确旋转轴
        loadingAnimation.setAxis(Rotate.Z_AXIS);
    }

    @Override
    public void initDimensions() {

    }


    @Override
    public void initData() {
        comThreadPool = ContextService.getBean(ComThreadPool.class);
    }

    @Override
    public void reactiveDimensions(double width, double height) {

    }

    @Override
    public void initListeners() {
        // 绑定按钮文本
        textLabel.textProperty().bind(textProperty());
        ComponentUtil.weakActionEventHandler(this, MouseEvent.MOUSE_ENTERED, stateHandler);
        ComponentUtil.weakActionEventHandler(this, MouseEvent.MOUSE_EXITED, stateHandler);
        ComponentUtil.weakActionEventHandler(this, MouseEvent.MOUSE_PRESSED, stateHandler);
        ComponentUtil.weakActionEventHandler(this, MouseEvent.MOUSE_RELEASED, stateHandler);
    }

    @Override
    public void dispose() {
        ComponentUtil.removeWeakListener(this, MouseEvent.MOUSE_ENTERED, stateHandler);
        ComponentUtil.removeWeakListener(this, MouseEvent.MOUSE_EXITED, stateHandler);
        ComponentUtil.removeWeakListener(this, MouseEvent.MOUSE_PRESSED, stateHandler);
        ComponentUtil.removeWeakListener(this, MouseEvent.MOUSE_RELEASED, stateHandler);
    }

    /**
     * fxml文件中调用
     */
    @Override
    public void fire() {
        handleAction();
    }


    /**
     * 执行按钮点击事件具体逻辑
     *
     * @param buttonEvent 按钮点击事件具体逻辑
     */
    public void actionEvent(ButtonEvent buttonEvent) {
        this.buttonEvent = buttonEvent;
    }

    public void action(Runnable runnableEvent) {
        Assert.notNull(runnableEvent, "按钮点击事件为空");
        this.buttonEvent = new ButtonEvent() {
            @Override
            public String getEventId() {
                if (StrUtil.isNotBlank(getText())) {
                    return getText();
                } else {
                    return "btn-" + System.currentTimeMillis() + "-" + hashCode();
                }
            }

            @Override
            public void execute() {
                runnableEvent.run();
            }
        };
    }

    private void handleAction() {
        if (isProcessing) {
            return;
        }
        isProcessing = true;
        updateUIState();
        // 如果未调用action方法buttonEvent对象为空，则调用子类实现的createButtonEvent获取ButtonEvent对象
        ButtonEvent childClassButtonEvent = createButtonEvent();
        if (childClassButtonEvent != null && this.buttonEvent == null) {
            actionEvent(childClassButtonEvent);
        }
        if (this.buttonEvent == null) {
            log.warn("按钮【{}】没有配置点击事件", this.textLabel.getText());
            return;
        }
        lastEventId = this.buttonEvent.getEventId();
        doHandleAction(this.buttonEvent, this::handleSuccess, this::handleFailure);
    }

    protected ButtonEvent createButtonEvent() {
        return null;
    }

    protected CompletableFuture<Void> doHandleAction(ButtonEvent event,
                                                     Runnable handleSuccess,
                                                     Runnable handleFailure) {
        return comThreadPool.runAsync(() -> {
            try {
                event.execute();
                handleSuccess.run();
            } catch (Exception e) {
                log.error("按钮操作执行失败: {}", e.getMessage(), e);
                handleFailure.run();
            }
        });
    }

    protected final void handleSuccess() {
        isProcessing = false;
        ComUtil.uiThreadRun(() -> {
            updateUIState();
            addTempStyleClass("success", Duration.seconds(2));
        });
        doHandleSuccess();
    }

    protected final void handleFailure() {
        isProcessing = false;
        ComUtil.uiThreadRun(() -> {
            updateUIState();
            addTempStyleClass("error", Duration.seconds(2));
        });
        doHandleFailure();
    }

    protected void doHandleSuccess() {

    }

    protected void doHandleFailure() {

    }
        protected void updateUIState() {
        ComUtil.uiThreadRun(() -> {
            setDisable(isProcessing);
            progressIndicator.setVisible(isProcessing);
            // 处理时隐藏文本
//            textLabel.setVisible(!isProcessing);
            if (isProcessing) {
                loadingAnimation.play();

//                getStyleClass().add("processing");
            } else {
                loadingAnimation.stop();
                // 重置旋转角度
                progressIndicator.setRotate(0);
//                getStyleClass().remove("processing");
            }
        });
    }

    public final void setSvgGraphic(Object svgGraphic) {
        SVGPath svgPath = null;
        if (svgGraphic instanceof String svgGraphicText) {
            svgPath = new SVGPath();
            svgPath.setContent(svgGraphicText);
        }
        svgGraphicProperty.bind(graphicProperty());
        setGraphic(createGraphicBox(textLabel, svgPath));
    }

    public final Object getSvgGraphic() {
        return getGraphic();
    }

    private Node createGraphicBox(Label textLabel, Node svgGraphic) {
        String buttonText = textLabel.getText();
        // 创建堆叠布局容器
        StackPane stackPane = new StackPane();
        stackPane.setAlignment(Pos.CENTER);
        if (svgGraphic != null && StrUtil.isBlank(buttonText)) {
            // 将文本和指示器添加到容器
            stackPane.getChildren().addAll(svgGraphic, progressIndicator);
            // 图标和文本的位置
            setContentDisplay(ContentDisplay.GRAPHIC_ONLY);
        }

        if (svgGraphic == null && StrUtil.isNotBlank(buttonText)) {
            // 将文本和指示器添加到容器
            stackPane.getChildren().addAll(textLabel, progressIndicator);
            // 图标和文本的位置
            setContentDisplay(ContentDisplay.GRAPHIC_ONLY);
        }

        if (svgGraphic != null && StrUtil.isNotBlank(buttonText)) {
            HBox hBox = new HBox();
            hBox.getChildren().addAll(svgGraphic, textLabel);
            stackPane.getChildren().addAll(hBox, progressIndicator);
            setContentDisplay(ContentDisplay.GRAPHIC_ONLY);
        }

        if (svgGraphic == null && StrUtil.isBlank(buttonText)) {
            // 将文本和指示器添加到容器
            stackPane.getChildren().addAll(progressIndicator);
        }

        return stackPane;
    }

    /**
     * 添加临时样式类
     *
     * @param styleClass 样式类名称
     * @param duration   持续时间
     */
    private void addTempStyleClass(String styleClass, Duration duration) {
        getStyleClass().add(styleClass);
        new Timeline(new KeyFrame(duration, e ->
                getStyleClass().remove(styleClass)
        )).play();
    }

    /**
     * 复用的事件处理器（减少对象创建）
     */
    private final EventHandler<MouseEvent> stateHandler = event -> {
        switch (event.getEventType().getName()) {
            case "MOUSE_ENTERED" -> handleHoverStart();
            case "MOUSE_EXITED" -> handleHoverEnd();
            case "MOUSE_PRESSED" -> handlePressStart();
            case "MOUSE_RELEASED" -> handlePressEnd();
            // 忽略其他事件
            default -> {

            }
        }
        updatePseudoClassStates();
    };

    /* 状态处理方法组 */
    private void handleHoverStart() {
        stateFlags |= HOVER_FLAG;
        playHoverAnimation(true);
    }

    private void handleHoverEnd() {
        stateFlags &= ~HOVER_FLAG;
        playHoverAnimation(false);
    }

    private void handlePressStart() {
        stateFlags |= PRESSED_FLAG;
        applyPressedStyle();
    }

    private void handlePressEnd() {
        stateFlags &= ~PRESSED_FLAG;
        applyReleaseStyle();
    }

    /**
     * 播放悬停动画（支持延迟初始化）
     *
     * @param enter true: 鼠标进入动画，false: 鼠标离开动画
     */
    private void playHoverAnimation(boolean enter) {
        // 双重检查锁定确保线程安全
        if (sharedFadeIn == null) {
            synchronized (AbstractButton.class) {
                if (sharedFadeIn == null) {
                    sharedFadeIn = createFadeTransition(1.0);
                    sharedFadeOut = createFadeTransition(DEFAULT_OPACITY);
                }
            }
        }

        FadeTransition anim = enter ? sharedFadeIn : sharedFadeOut;
        if (anim.getStatus() == Animation.Status.RUNNING) {
            // 停止正在运行的动画避免冲突
            anim.stop();
        }
        // 绑定当前节点
        anim.setNode(this);
        anim.playFromStart();
    }

    private static FadeTransition createFadeTransition(double toValue) {
        FadeTransition ft = new FadeTransition(DEFAULT_ANIM_DURATION);
        ft.setFromValue(DEFAULT_OPACITY);
        ft.setToValue(toValue);
        return ft;
    }

    /**
     * 应用按下样式（默认缩小5%）
     */
    protected void applyPressedStyle() {

    }

    /**
     * 应用释放样式（默认恢复原尺寸）
     */
    protected void applyReleaseStyle() {

    }

    private void updatePseudoClassStates() {
        pseudoClassStateChanged(HOVER_PSEUDO_CLASS, (stateFlags & HOVER_FLAG) != 0);
        pseudoClassStateChanged(PRESSED_PSEUDO_CLASS, (stateFlags & PRESSED_FLAG) != 0);
    }

    public void clearEvent(Runnable runnable) {
        this.buttonEvent = null;
    }
}
